package com.sinosoft.builder.config;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import java.util.logging.Logger;

import com.sinosoft.builder.parser.SinoParser;
import com.sinosoft.builder.parser.SinoParserType;
import com.sinosoft.builder.templates.concept.AssociationConceptBetweenDomainConcepts;
import com.sinosoft.builder.templates.concept.BehaviorConcept;
import com.sinosoft.builder.templates.concept.BehaviorConceptRef;
import com.sinosoft.builder.templates.concept.BehaviorCriterionConcept;
import com.sinosoft.builder.templates.concept.BehaviorCriterionConceptDependence;
import com.sinosoft.builder.templates.concept.BehaviorDependenceConcept;
import com.sinosoft.builder.templates.concept.BusinessConcept;
import com.sinosoft.builder.templates.concept.BusinessDomainConcept;
import com.sinosoft.builder.templates.concept.CodeSet;
import com.sinosoft.builder.templates.concept.ComplexBehaviorCriterionConceptRef;
import com.sinosoft.builder.templates.concept.ComplexBehaviorCriterionConceptType;
import com.sinosoft.builder.templates.concept.ComplexContentConceptType;
import com.sinosoft.builder.templates.concept.Constitution;
import com.sinosoft.builder.templates.concept.ContentConceptRefSet;
import com.sinosoft.builder.templates.concept.ContentConceptSet;
import com.sinosoft.builder.templates.concept.DictionaryCodingConcept;
import com.sinosoft.builder.templates.concept.Document;
import com.sinosoft.builder.templates.concept.DocumentConcept;
import com.sinosoft.builder.templates.concept.EntityConcept;
import com.sinosoft.builder.templates.concept.NamingElement;
import com.sinosoft.builder.templates.concept.PrimitiveBehaviorCriterionConceptType;
import com.sinosoft.builder.templates.concept.PrimitiveContentConceptType;
import com.sinosoft.builder.templates.concept.RoleConcept;
import com.sinosoft.builder.templates.concept.RoleConceptRef;
import com.sinosoft.builder.templates.concept.SearchForm;
import com.sinosoft.builder.templates.concept.SearchFormConcept;
import com.sinosoft.builder.templates.concept.SubContentConceptGroup;
import com.sinosoft.builder.utils.BusinessConceptTableType;

/**
 * 元数据处理帮助类
 * 
 * @author 潘巍（Peter Pan）
 * @since 2010-12-8 下午02:56:37
 */
public class BusinessConceptHelper {

	private static final Logger logger = Logger
			.getLogger(BusinessConceptHelper.class.getName());

	public static final String DOT = ".";

	public static final String DEFAULT_PACKAGE = "com.sinosoft.dsp.persistence.businessconcept";

	public static final String DEFAULT_PREFIX = "R";

	/**
	 * 工具方法：获得业务概念的表实体类
	 * 
	 * @param type
	 * @return
	 * @throws ClassNotFoundException
	 */
	public static Class<?> getBusinessConceptTableClass(
			BusinessConceptTableType type) throws ClassNotFoundException {
		return getBusinessConceptTableClass(null, null, type);
	}

	/**
	 * 工具方法：获得业务概念的表实体类
	 * 
	 * @param packageName
	 * @param prefix
	 * @param type
	 * @return
	 * @throws ClassNotFoundException
	 */
	public static Class<?> getBusinessConceptTableClass(String packageName,
			String prefix, BusinessConceptTableType type)
			throws ClassNotFoundException {
		return Class.forName(getBusinessConceptTableClassName(packageName,
				prefix, type));
	}

	/**
	 * 工具方法：获得业务概念的表实体类名称
	 * 
	 * @param packageName
	 * @param prefix
	 * @param type
	 * @return
	 */
	public static String getBusinessConceptTableClassName(
			BusinessConceptTableType type) {
		return getBusinessConceptTableClassName(null, null, type);
	}

	/**
	 * 工具方法：获得业务概念的表实体类名称
	 * 
	 * @param packageName
	 * @param prefix
	 * @param type
	 * @return
	 */
	public static String getBusinessConceptTableClassName(String packageName,
			String prefix, BusinessConceptTableType type) {
		return getPackageName(packageName) + DOT + getPrefix(prefix)
				+ type.getEntityName();
	}

	/**
	 * 工具方法：通过设置值获得包名
	 * 
	 * @return
	 */
	public static String getPackageName() {
		return getPackageName(null);
	}

	/**
	 * 工具方法：通过设置值获得包名
	 * 
	 * @param value
	 * @return
	 */
	public static String getPackageName(String value) {
		if (value == null || "".equals(value.trim())) {
			return DEFAULT_PACKAGE;
		} else {
			return value.trim();
		}
	}

	/**
	 * 工具方法：通过设置值获得前缀
	 * 
	 * @return
	 */
	public static String getPrefix() {
		return getPrefix(null);
	}

	/**
	 * 工具方法：通过设置值获得前缀
	 * 
	 * @param value
	 * @return
	 */
	public static String getPrefix(String value) {
		if (value == null || "".equals(value.trim())) {
			return DEFAULT_PREFIX;
		} else {
			return value.trim().toUpperCase();
		}
	}

	/**
	 * 工具方法：判断对象是否是目录
	 * 
	 * @param f
	 * @return
	 */
	public static boolean isDirectory(File f) {
		if (f != null && f.exists() && f.isDirectory()) {
			return true;
		}
		return false;
	}

	/**
	 * 工具方法：加载业务概念元数据（对于代码表和文书不进行缓存，只判断其根ID是否重复）
	 * 
	 * @param bc
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> loadBusinessConceptMetas(
			BusinessConcept bc) {
		Object[] rtn = cacheBusinessConcept(bc);
		if (rtn != null) {
			rtn[0] = null;
			return (Map<String, Object>) rtn[1];
		}
		return null;
	}

	/**
	 * 工具方法：验证业务概念对象
	 * 
	 * @param bc
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static List<String> validationBusinessConcept(BusinessConcept bc) {
		Object[] rtn = cacheBusinessConcept(bc);
		if (rtn != null) {
			rtn[1] = null;
			return (List<String>) rtn[0];
		}
		return null;
	}

	private static Object[] cacheBusinessConcept(BusinessConcept bc) {
		List<String> rtn = new ArrayList<String>();
		if (bc != null) {
			BusinessDomainConcept domain = bc.getBusinessDomainConcept();
			Map<String, Object> cache = new HashMap<String, Object>();
			// 1.验证实体概念
			for (EntityConcept ec : domain.getEntityConcept())
				validateEntityConcept(rtn, cache, ec);
			// 2.验证角色概念
			for (RoleConcept rc : domain.getRoleConcept())
				validateRoleConcept(rtn, cache, rc);
			// 3.验证角色概念间的关联概念
			for (AssociationConceptBetweenDomainConcepts acbrc : domain
					.getAssociationConceptBetweenDomainConcepts())
				validateAssociationConceptBetweenRoleConcepts(rtn, cache, acbrc);
			// 4.验证行为概念
			for (BehaviorConcept bec : domain.getBehaviorConcept())
				validateBehaviorConcept(rtn, cache, bec);
			// 5.验证场景概念
			// 6.验证业务规范概念
			validateBehaviorCriterionConcept(rtn, cache, bc
					.getBehaviorCriterionConcept());
			// 7.验证代码表概念-只验证根ID是否重复，同时只缓存根对象
			if (bc.getDictionaryCodingConcept() != null)
				for (CodeSet cs : bc.getDictionaryCodingConcept().getCodeSet())
					validateCodeSet(rtn, cache, cs);
			// 8.验证文书概念-只验证根ID是否重复，同时只缓存根对象
			if (bc.getDocumentConcept() != null) {
				for (Document d : bc.getDocumentConcept().getDocument())
					validateDocument(rtn, cache, d);

			}
			return new Object[] { rtn, cache };
		}
		return null;
	}

	private static void validateDocument(List<String> rtn,
			Map<String, Object> entities, Document d) {
		if (entities.containsKey(d.getId())) {
			rtn.add("“文书”出现重复ID : " + d.getId() + " , Name : " + d.getName());
		}
	}

	private static void validateCodeSet(List<String> rtn,
			Map<String, Object> entities, CodeSet cs) {
		if (entities.containsKey(cs.getId())) {
			rtn
					.add("“代码表”出现重复ID : " + cs.getId() + " , Name : "
							+ cs.getName());
		}
	}

	private static void validateBehaviorCriterionConcept(List<String> rtn,
			Map<String, Object> entities, BehaviorCriterionConcept bcc) {
		if (bcc != null) {
			// 行为依赖概念
			for (BehaviorDependenceConcept bdc : bcc
					.getBehaviorDependenceConcept())
				validateBehaviorDependenceConcept(rtn, entities, bdc);

			// 简单行为规范概念
			for (PrimitiveBehaviorCriterionConceptType pbcc : bcc
					.getPrimitiveBehaviorCriterionConcept())
				validatePrimitiveBehaviorCriterionConceptType(rtn, entities,
						pbcc);

			// 复合行为规范概念
			for (ComplexBehaviorCriterionConceptType cbcc : bcc
					.getComplexBehaviorCriterionConcept())
				validateComplexBehaviorCriterionConceptType(rtn, entities, cbcc);

			// 行为规范概念之间的依赖的描述
			for (BehaviorCriterionConceptDependence bccd : bcc
					.getBehaviorCriterionConceptDependence())
				validateBehaviorCriterionConceptDependence(rtn, entities, bccd);
		}
	}

	private static void validateBehaviorDependenceConcept(List<String> rtn,
			Map<String, Object> entities, BehaviorDependenceConcept bdc) {
		if (entities.containsKey(bdc.getId())) {
			rtn.add("“行为依赖概念”出现重复ID : " + bdc.getId());
		} else {
			entities.put(bdc.getId(), bdc);
		}
	}

	private static void validateComplexBehaviorCriterionConceptType(
			List<String> rtn, Map<String, Object> entities,
			ComplexBehaviorCriterionConceptType cbcc) {
		if (entities.containsKey(cbcc.getId())) {
			rtn.add("“简单行为规范概念”出现重复ID : " + cbcc.getId() + " , Step : "
					+ cbcc.getStep());
		} else {
			entities.put(cbcc.getId(), cbcc);
		}
		// 命名元素
		for (NamingElement ne : cbcc.getNamingElement())
			validateNamingElement(rtn, entities, ne);

		// Constitution
		validateConstitution(rtn, entities, cbcc.getConstitution());
	}

	private static void validateConstitution(List<String> rtn,
			Map<String, Object> entities, Constitution constitution) {
		if (constitution != null) {
			// 简单行为规范概念
			for (PrimitiveBehaviorCriterionConceptType pbcc : constitution
					.getPrimitiveBehaviorCriterionConcept())
				validatePrimitiveBehaviorCriterionConceptType(rtn, entities,
						pbcc);

			// 复合行为规范概念引用
			for (ComplexBehaviorCriterionConceptRef cbcc : constitution
					.getComplexBehaviorCriterionConceptRef())
				validateComplexBehaviorCriterionConceptRef(rtn, entities, cbcc);
		}
	}

	private static void validateComplexBehaviorCriterionConceptRef(
			List<String> rtn, Map<String, Object> entities,
			ComplexBehaviorCriterionConceptRef cbcc) {
		if (entities.containsKey(cbcc.getId())) {
			rtn.add("“复合行为规范概念引用”出现重复ID : " + cbcc.getId());
		} else {
			entities.put(cbcc.getId(), cbcc);
		}
	}

	private static void validatePrimitiveBehaviorCriterionConceptType(
			List<String> rtn, Map<String, Object> entities,
			PrimitiveBehaviorCriterionConceptType pbcc) {
		if (entities.containsKey(pbcc.getId())) {
			rtn.add("“简单行为规范概念”出现重复ID : " + pbcc.getId() + " , Step : "
					+ pbcc.getStep());
		} else {
			entities.put(pbcc.getId(), pbcc);
		}

		// 命名元素
		for (NamingElement ne : pbcc.getNamingElement())
			validateNamingElement(rtn, entities, ne);

		// 行为概念引用
		for (BehaviorConceptRef bcr : pbcc.getBehaviorConceptRef())
			validateBehaviorConceptRef(rtn, entities, bcr);
	}

	private static void validateBehaviorCriterionConceptDependence(
			List<String> rtn, Map<String, Object> entities,
			BehaviorCriterionConceptDependence bccd) {
		if (entities.containsKey(bccd.getId())) {
			rtn.add("“行为规范概念之间的依赖的描述”出现重复ID : " + bccd.getId());
		} else {
			entities.put(bccd.getId(), bccd);
		}
	}

	private static void validateBehaviorConcept(List<String> rtn,
			Map<String, Object> entities, BehaviorConcept bec) {
		if (entities.containsKey(bec.getId())) {
			rtn.add("“行为概念”出现重复ID : " + bec.getId() + " , Name : "
					+ bec.getName());
		} else {
			entities.put(bec.getId(), bec);
		}

		// 命名元素
		for (NamingElement ne : bec.getNamingElement())
			validateNamingElement(rtn, entities, ne);

		// 角色内容引用
		for (RoleConceptRef rcr : bec.getRoleConceptRef())
			validateRoleConceptRef(rtn, entities, rcr);

		// 内容概念集
		validateContentConceptSet(rtn, entities, bec.getContentConceptSet());

	}

	private static void validateRoleConceptRef(List<String> rtn,
			Map<String, Object> entities, RoleConceptRef rcr) {
		if (entities.containsKey(rcr.getId())) {
			rtn.add("“角色内容引用”出现重复ID : " + rcr.getId());
		} else {
			entities.put(rcr.getId(), rcr);
		}
	}

	private static void validateBehaviorConceptRef(List<String> rtn,
			Map<String, Object> entities, BehaviorConceptRef bcr) {
		if (entities.containsKey(bcr.getId())) {
			rtn.add("“行为概念引用”出现重复ID : " + bcr.getId());
		} else {
			entities.put(bcr.getId(), bcr);
		}
	}

	private static void validateAssociationConceptBetweenRoleConcepts(
			List<String> rtn, Map<String, Object> entities,
			AssociationConceptBetweenDomainConcepts acbrc) {
		if (entities.containsKey(acbrc.getId())) {
			rtn.add("“角色概念间的关联概念”出现重复ID : " + acbrc.getId() + " , Name : "
					+ acbrc.getName());
		} else {
			entities.put(acbrc.getId(), acbrc);
		}

		// 命名元素
		for (NamingElement ne : acbrc.getNamingElement())
			validateNamingElement(rtn, entities, ne);
	}

	private static void validateRoleConcept(List<String> rtn,
			Map<String, Object> entities, RoleConcept rc) {
		if (entities.containsKey(rc.getId())) {
			rtn.add("“角色概念”出现重复ID : " + rc.getId() + " , Name : "
					+ rc.getName());
		} else {
			entities.put(rc.getId(), rc);
		}

		// 命名元素
		for (NamingElement ne : rc.getNamingElement())
			validateNamingElement(rtn, entities, ne);

		// 内容概念引用
		for (ContentConceptRefSet ccrs : rc.getContentConceptRefSet())
			validateContentConceptRefSet(rtn, entities, ccrs);
	}

	private static void validateContentConceptRefSet(List<String> rtn,
			Map<String, Object> entities, ContentConceptRefSet ccrs) {
		if (entities.containsKey(ccrs.getId())) {
			rtn.add("“内容概念引用集”出现重复ID : " + ccrs.getId());
		} else {
			entities.put(ccrs.getId(), ccrs);
		}
	}

	private static void validateEntityConcept(List<String> rtn,
			Map<String, Object> entities, EntityConcept ec) {
		if (entities.containsKey(ec.getId())) {
			rtn.add("“实体概念”出现重复ID : " + ec.getId() + " , Name : "
					+ ec.getName());
		} else {
			entities.put(ec.getId(), ec);
		}
		// 命名元素
		for (NamingElement ne : ec.getNamingElement())
			validateNamingElement(rtn, entities, ne);

		// 内容概念集
		validateContentConceptSet(rtn, entities, ec.getContentConceptSet());
	}

	private static void validateContentConceptSet(List<String> rtn,
			Map<String, Object> entities, ContentConceptSet ccs) {
		if (ccs != null) {
			for (ComplexContentConceptType ccc : ccs.getComplexContentConcept())
				validateComplexContentConcept(rtn, entities, ccc);

			for (PrimitiveContentConceptType pcc : ccs
					.getPrimitiveContentConcept())
				validatePrimitiveContentConcept(rtn, entities, pcc);
		}
	}

	private static void validatePrimitiveContentConcept(List<String> rtn,
			Map<String, Object> entities, PrimitiveContentConceptType pcc) {
		if (entities.containsKey(pcc.getId())) {
			rtn.add("“实体概念-私有内容概念”出现重复ID : " + pcc.getId() + " , Name : "
					+ pcc.getName());
		} else {
			entities.put(pcc.getId(), pcc);
		}

		for (NamingElement ne : pcc.getNamingElement())
			validateNamingElement(rtn, entities, ne);
	}

	private static void validateComplexContentConcept(List<String> rtn,
			Map<String, Object> entities, ComplexContentConceptType ccc) {
		if (entities.containsKey(ccc.getId())) {
			rtn.add("“实体概念-复合内容概念”出现重复ID : " + ccc.getId() + " , Name : "
					+ ccc.getName());
		} else {
			entities.put(ccc.getId(), ccc);
		}

		for (NamingElement ne : ccc.getNamingElement())
			validateNamingElement(rtn, entities, ne);

		for (SubContentConceptGroup sccg : ccc.getSubContentConceptGroup())
			validateSubContentConceptGroup(rtn, entities, sccg);
	}

	private static void validateSubContentConceptGroup(List<String> rtn,
			Map<String, Object> entities, SubContentConceptGroup sccg) {
		if (entities.containsKey(sccg.getId())) {
			rtn.add("“实体概念-复合内容概念-子内容概念组”出现重复ID : " + sccg.getId()
					+ " , GroupKind : " + sccg.getGroupKind());
		} else {
			entities.put(sccg.getId(), sccg);
		}
	}

	private static void validateNamingElement(List<String> rtn,
			Map<String, Object> entities, NamingElement ne) {
		if (entities.containsKey(ne.getId())) {
			rtn.add("“命名元素”出现重复ID : " + ne.getId() + " , FullName : "
					+ ne.getFullName());
		} else {
			entities.put(ne.getId(), ne);
		}
	}

	/**
	 * 工具方法：解析业务领域
	 * 
	 * @param t
	 * @param file
	 * @throws IOException
	 */
	public static BusinessConcept parseBussinessConcept(SinoParserType t)
			throws IOException {
		File file = SinoParser.getXMLFile(t);
		logger.info("concept dir:" + ((file != null) ? file.getName() : ""));
		if (isDirectory(file)) {
			BusinessConcept bc = new BusinessConcept();

			// 1.解析业务领域概念
			BusinessDomainConcept bdc = new BusinessDomainConcept();
			bc.setBusinessDomainConcept(bdc);

			// 1-1.解析实体概念
			List<EntityConcept> entities = SinoParserType.BUSSINESSCONCEPT_ENTITY
					.parser();
			if (entities != null)
				for (EntityConcept ec : entities) {
					bdc.getEntityConcept().add(ec);
				}

			// 1-2.解析角色概念
			List<RoleConcept> roles = SinoParserType.BUSSINESSCONCEPT_ROLE
					.parser();
			if (roles != null)
				for (RoleConcept rc : roles) {
					bdc.getRoleConcept().add(rc);
				}

			// 1-3.解析角色概念间的关联概念
			List<AssociationConceptBetweenDomainConcepts> assoRoles = SinoParserType.BUSSINESSCONCEPT_ASSOCIATIONCONCEPTDOMAIN
					.parser();
			if (assoRoles != null)
				for (AssociationConceptBetweenDomainConcepts a : assoRoles) {
					bdc.getAssociationConceptBetweenDomainConcepts().add(a);
				}

			// 1-4.解析行为概念
			List<BehaviorConcept> behaviors = SinoParserType.BUSSINESSCONCEPT_BEHAVIOR
					.parser();
			if (behaviors != null)
				for (BehaviorConcept b : behaviors) {
					bdc.getBehaviorConcept().add(b);
				}

			// 1-5.解析场景概念

			// 2.解析业务规范概念
			BehaviorCriterionConcept bcc = new BehaviorCriterionConcept();
			bc.setBehaviorCriterionConcept(bcc);
			List<BehaviorCriterionConcept> criterions = SinoParserType.BUSSINESSCONCEPT_BEHAVIORCRITERION
					.parser();
			if (criterions != null)
				for (BehaviorCriterionConcept c : criterions) {
					if (c.getBehaviorCriterionConceptDependence() != null)
						bcc.getBehaviorCriterionConceptDependence().addAll(
								c.getBehaviorCriterionConceptDependence());
					if (c.getPrimitiveBehaviorCriterionConcept() != null)
						bcc.getPrimitiveBehaviorCriterionConcept().addAll(
								c.getPrimitiveBehaviorCriterionConcept());
					if (c.getComplexBehaviorCriterionConcept() != null)
						bcc.getComplexBehaviorCriterionConcept().addAll(
								c.getComplexBehaviorCriterionConcept());
					if (c.getBehaviorDependenceConcept() != null)
						bcc.getBehaviorDependenceConcept().addAll(
								c.getBehaviorDependenceConcept());
				}

			// 3.解析代码表概念
			DictionaryCodingConcept dcc = new DictionaryCodingConcept();
			bc.setDictionaryCodingConcept(dcc);
			List<CodeSet> codesets = SinoParserType.BUSSINESSCONCEPT_CODESET
					.parser();
			if (codesets != null)
				for (CodeSet c : codesets) {
					dcc.getCodeSet().add(c);
				}

			// 4.解析文书概念
			DocumentConcept dc = new DocumentConcept();
			bc.setDocumentConcept(dc);
			List<Document> documents = SinoParserType.BUSSINESSCONCEPT_DOCUMENT
					.parser();
			if (documents != null)
				for (Document d : documents) {
					dc.getDocument().add(d);
				}

			// 5.解析查询表单概念
			SearchFormConcept sfc = new SearchFormConcept();
			bc.setSearchFormConcept(sfc);
			List<SearchForm> searchForms = SinoParserType.BUSSINESSCONCEPT_SEARCHFORM
					.parser();
			if (searchForms != null) {
				for (SearchForm sf : searchForms) {
					sfc.getSearchForm().add(sf);
				}
			}

			return bc;
		}
		return null;

	}

}
